; Created Time: 2022年5月16日 17:07:08
; Author: Eric

; 实现任务切换函数 task_switch

[bits 32]

section .text   ; 代码段

; task_switch 传递一个输入参数target_t *next
global task_switch  ; 全局可见，链接器解析
task_switch:
    push ebp
    mov ebp, esp    ; 保存栈帧

    ; 保存System V调用约定需要保存的寄存器（包括ebp）
    push ebx
    push esi
    push edi

    ; esp最后12位与为0，esp存放的是当前线程的栈顶
    mov eax, esp
    and eax, 0xfffff000 ; current

    mov [eax], esp  ; esp此时是当前线程的栈顶，存至[eax]中

    mov eax, [ebp + 8] ; 取出传进来的下一个参数, next
    mov esp, [eax]     ; 将该参数的栈顶恢复至esp，即切换栈顶

    ; 没有恢复esp，如果恢复esp，那么esp指向的就是current，而不是next
    pop edi
    pop esi
    pop ebx
    pop ebp

    ret